<template>
  <div class="login_wrap"
       v-loading="loading"
       element-loading-text="登录中..."
       element-loading-spinner="el-icon-loading">
    <div class="login_f">
      <div class="login">
        <a class="title">{{activeIndex === 1 ? '账号登录' : 'Ukey登录'}}</a>
        <div class="form">
          <div class="tabs">
            <span v-for="item in tab"
                  :key="item.key"
                  :class="{ 'active': activeIndex === item.key}"
                  @click="changeTab($event, item.key)">
              {{item.name}}
            </span>
          </div>
          <div class="error"
               :style="{ opacity: errorMsg? 1 : 0 }">
            {{errorMsg}}
          </div>
          <div class="tab_content">
            <div class="tab_1"
                 v-show="activeIndex === 1">
              <div class="login_item">
                <el-input size="small"
                          v-model="userName"
                          placeholder="支持UID、姓名、邮箱、手机号、账号登录"
                          class="ipt">
                  <template slot="prefix">
                    <span>账号</span>
                  </template>
                </el-input>
              </div>

              <div class="login_item">
                <el-input size="small"
                          v-model="password"
                          type="password"
                          class="ipt"
                          placeholder="输入密码">
                  <span slot="prefix">密码</span>
                </el-input>
              </div>
              <div class="login_item">
                <el-input size="small"
                          v-model="validCode"
                          class="ipt"
                          placeholder="输入验证码"
                          @keyup.enter.native="handleSubmit">
                  <span slot="prefix">验证码</span>
                </el-input>
                <img :src="valiCodeImg"
                     alt=""
                     @click="getCaptchaFn" />
              </div>
            </div>

            <div class="tab_2"
                 v-show="activeIndex === 2"
                 v-loading="keyLoading"
                 element-loading-text="初始化中..."
                 element-loading-spinner="el-icon-loading"
                 element-loading-background="rgba(4, 12, 32, 0.45)">
              <div class="login_item selectX">
                <span slot="prefix">证书</span>
                <el-select size="small"
                           placeholder="选择证书"
                           v-model="selectedCert">
                  <el-option v-for="item in certList"
                             :key="item.deviceSn"
                             :label="item.subjectCN"
                             :value="item.subjectCN">
                  </el-option>
                </el-select>
              </div>
              <div class="login_item">
                <el-input size="small"
                          v-model="uk_password"
                          type="password"
                          class="ipt"
                          @keyup.enter.native="handleSubmit"
                          placeholder="输入密码">

                  <span slot="prefix">密码</span>
                </el-input>
              </div>
              <div class="login_item">
                <div class="login_unlock">
                  ukey解锁
                </div>
                <span :style="{ display: 'none' }"> {cert}</span>
              </div>
            </div>
            <div class="btn">
              <el-button type="primary"
                         @click="handleSubmit($event)">
                登录
              </el-button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>

import { Login, getRSAKey, getOauthInfo, LoginParams, getUkeyRsaPassword, listMenuBtn, enterPact, getContactTree } from '../../api/token';
import {
  getCertList, getUserList, getUserInfo, verifyPwd, verifyPwdCA, checkServer, getCertAllInfo,
  getCertInfoByOID, getCertPicture
} from '../../utils/wp-sign-func';
import moment from 'moment';
import { Base64 } from 'js-base64';
import { apiUrl, SYSTEMTYPE } from '../../config/index'
import { guid } from '../../utils/index'
import { setappServerId, setToken, setRefreshToken, setProjIds, setCatalog } from '../../utils/auth'
import { mapState, mapGetters } from 'vuex'
let Wi = window;
let RSAUtils = Wi.RSAUtils;
export default {
  name: "Login",
  data() {
    return {
      loading: false,
      keyLoading: true,
      loadingTxt: "",
      activeIndex: 2,
      errorMsg1: "",
      errorMsg2: "",
      selectedCert: "",
      certList: [],
      tab: [{
        name: '账号登录',
        key: 1,
      }, {
        name: 'Ukey登录',
        key: 2,
      }],
      loginTag: 0,
      userName: '',
      password: '',
      validCode: '',
      validCodeKey: '',
      ignoreComplexPwd: 0,
      uk_password: '',
      uuId: '',
      valiCodeImg: '',
      isLowComplex: false,
      isAuto: false
    };
  },
  created() {
    this.getCaptchaFn();
    this.changeTab(undefined, this.activeIndex);
  },
  methods: {
    getCaptchaFn() {
      const uuId = guid();
      const valiCodeImg = `${apiUrl}/bspallas-admin/admin/captcha?validCodeKey=` + uuId + '&t=' + new Date().toUTCString();
      this.uuId = uuId;
      this.valiCodeImg = valiCodeImg;
    },
    changeTab(e, tab) {
      this.activeIndex = tab;
      if (tab === 2) {
        if (SYSTEMTYPE !== 'sz') {
          /* 其他登录状态下 登录界面加载证书 */
          checkServer()
            .then((res) => {
              this.keyLoading = false;
              this.errorMsg2 = '';
              this.getUkeyList();
            })
            .catch((res) => {
              this.keyLoading = false;
              this.errorMsg2 = '请确认已安装数字证书驱动并开启了客户端';
            });
        } else {
          this.keyLoading = false;
          this.errorMsg2 = '';
          this.getUkeyList();
        }
      }
    },
    async getUkeyList(isSZAuto = false, getCb) {
      let list = await (SYSTEMTYPE === 'sz' ? getUserList() : getCertList()) || [];
      if (list.length) {
        this.certList = list;
        getCb && getCb(list);
        // isSZAuto && this.getOauthInfoFn();
        this.$store.commit('SET_RECERT');
      }
      if (list.length === 1 && !getCb) {
        this.selectedCert = list[0];
        // this.selectedCert.type === 'ca' && this.caKey();
      } else {
        this.isAuto = false;
      }
    },
    async handleSubmit(e, defaultPw = false, account) {
      console.log('---');
      switch (this.activeIndex) {
        case 1:
          this.accountLogin();
          break;
        case 2:
          this.ukeyLogin(0, defaultPw, account);
          break;
        // case 3:
        //   this.toLogin();
        //   break;
      }
    },
    async accountLogin(ignoreComplexPwd) {
      const { userName, password, validCode, uuId } = this;
      let option = {
        loginTag: 0,
        password,
        username: userName,
        validCode: validCode,
        validCodeKey: uuId,
        ignoreComplexPwd: ignoreComplexPwd || 0,
      }
      if (!password.trim()) {
        this.errorMsg1 = '密码不能为空';
        return;
      }
      if (!validCode.trim()) {
        this.errorMsg1 = '请输入验证码';
        return;
      }
      this.loading = true;
      this.loadingTxt = '登录中...';

      let RSAKey = await getRSAKey({ key: uuId });
      RSAUtils.setMaxDigits(200);
      let publicKey = new RSAUtils.getKeyPair(RSAKey.data.data.exponent, '', RSAKey.data.data.modulus);
      let encrypedPwd = RSAUtils.encryptedString(publicKey, password.split('').reverse().join(''));
      option['password'] = encrypedPwd;
      let res = await Login(option);
      let resData = res.data;
      const { code, data } = resData;
      if (code === 200) {
        this.loading = false;
        this.loadingTxt = '';
        this.storeData(data);
        if (data.pwdOverTimeMsg) {
          this.$message(data.pwdOverTimeMsg);
        }
        this.isLowComplex = false;
        this.$router.replace('/admin/home');

      } else if (resData.message === '密码复杂度不满足要求') {
        this.loading = false;
        this.errorMsg1 = '';
        this.isLowComplex = true;
        this.userName = userName;
        this.password = password;
        this.$alert('您的密码复杂度较低，建议您去修改密码，密码中必须包含大写及小写字母、数字、特殊字符，且至少8位字符，最多30位字符。', '提示', {
          confirmButtonText: '确定',
          callback: action => {
            this.accountLogin(1);
          }
        });
      } else {
        this.getCaptchaFn();
        this.validCode = '';
        this.loading = false;
        this.isLowComplex = false;
        this.errorMsg1 = resData.message;
      }
    },
    async ukeyLogin(ignoreComplexPwd, defaultPW, account) {
      let { uk_password, uuId, selectedCert, ip, searchParams } = this;
      const isCA = this.selectedCert.type && this.selectedCert.type === 'ca';
      // 轨道不允许非个人证书登录
      if (SYSTEMTYPE === 'sz' && selectedCert.signThumbprint.substr(selectedCert.signThumbprint.indexOf('5009') + 4, 2) == 'JJ') {
        this.errorMsg2 = '非个人证书不允许登录系统，请重新选择证书!';
        return;
      }

      let RSAKey = await getRSAKey({ key: uuId });
      RSAUtils.setMaxDigits(200);
      const publicKey = new RSAUtils.getKeyPair(RSAKey.data.data.exponent, '', RSAKey.data.data.modulus);
      const encrypedPwd = RSAUtils.encryptedString(publicKey, (selectedCert.Thumbprint || selectedCert.signThumbprint).split('').reverse().join(''));

      if (!selectedCert.deviceSn) {
        this.errorMsg2 = '请选择证书';
        return;
      }
      if (!uk_password) {
        this.errorMsg2 = '密码不能为空';
        return;
      }
      this.loading = true;
      this.loadingTxt = "登录中...";
      try {
        let res = await verifyPwd(selectedCert.deviceSn, selectedCert.deviceType, uk_password);

        if (res.result === 1) {
          const encrypedUkeyPwd = RSAUtils.encryptedString(publicKey, uk_password.split('').reverse().join(''));
          let ukeyCertVo = {
            keyId: isCA ? selectedCert.subjectCN : selectedCert.subjectCN,
            keySerial: isCA ? selectedCert.Sign_ID.split('/')[1] : selectedCert.deviceSn,
            signId: isCA ? selectedCert.key_Serial : selectedCert.serialNumber,
            caBdate: moment(this.formateDate(isCA ? selectedCert.CA_BDate : selectedCert.validFromDate, true), 'YYYY-MM-DD hh:mm:ss').format(
              'YYYY-MM-DD hh:mm:ss'
            ),
            caEdate: moment(this.formateDate(isCA ? selectedCert.CA_EDate : selectedCert.validToDate, true), 'YYYY-MM-DD hh:mm:ss').format(
              'YYYY-MM-DD hh:mm:ss'
            ),
            caCsp: isCA ? selectedCert.CA_CSP : selectedCert.issuer,
            remarkSign: selectedCert.subject,
            signThumbprint: isCA ? selectedCert.signThumbprint : selectedCert.Thumbprint,
            signCert: isCA ? selectedCert.Sign_Cert : selectedCert.certCode,
            cryptCert: isCA ? selectedCert.Crypt_Cert : selectedCert.crptCert,
            preThumbprint: selectedCert.preThumbprint,
            name: selectedCert.subjectCN,
            idno: selectedCert.idCard && Base64.encode(selectedCert.idCard),
            ukeyPassword: encrypedUkeyPwd,
            account
          };
          const data = {
            loginTag: 3,
            password: selectedCert.subjectCN,
            username: encrypedPwd,
            validCode: '',
            validCodeKey: uuId,
            ignoreComplexPwd: ignoreComplexPwd || 0,
            // ip: ip ? ip : (window as any).returnCitySN?.cip,
            ukeyCertVo,
          };
          const resq = await Login(data);
          if (resq.data.code === 200) {
            const data = resq.data.data;
            this.storeData(data);
            this.$store.commit('SET_CERT', {
              value: selectedCert.Thumbprint,
              certsn: selectedCert.deviceSn,
              deviceType: selectedCert.deviceType,
              password: uk_password,
              signId: data.certSN,
              validToDate: ukeyCertVo.caEdate
            });
            this.$router.replace('/admin/home');
            //缓存密码
            // window.deviceTimer = setInterval(() => {
            //   if (isCA) {
            //     verifyPwdCA(selectedCert.deviceSn, uk_password);
            //   } else {
            //     verifyPwd(selectedCert.deviceSn, selectedCert.deviceType, uk_password);
            //   }
            // }, 60000 * 30);

          } else if (resq.data.message === '密码复杂度不满足要求') {
            this.loading = false;
            this.errorMsg2 = '';
            this.$alert('您的密码复杂度较低，建议您去修改密码，密码中必须包含大写及小写字母、数字、特殊字符，且至少8位字符，最多30位字符。', '提示', {
              confirmButtonText: '确定',
              callback: action => {
                this.ukeyLogin(1, defaultPW);
              }
            });
          } else {
            this.loading = false;
            this.errorMsg2 = resq.data.message;
          }
        } else {
          this.loading = false;
          this.errorMsg2 = `密码错误,您还有剩余${res.retrynum}次机会`;
        }
      }
      catch (err) {
        this.loading = false;
        this.errorMsg2 = err.msg;
      } finally {
      }
    },
    storeData(data) {
      const token = 'Bearer ' + data.token.access_token;
      const { userName, userId, pactName, pactId, projName, projId, loginType, topProjId, connectId, mustUKeySign, roadLevel, roadLevelName, isAdmin, pactType, isSelfPact } = data;
      this.$store.commit('SET_LOGINDATA', {
        userName,
        userId: String(userId),
        pactName,
        pactId: pactId || 0,
        projName,
        projId: projId || '',
        loginType,
        topProjId: topProjId || '',
        connectId,
        mustUKeySign,
        roadLevel: roadLevel || 0,
        roadLevelName,
        isAdmin,
        token,
        pactType: pactType || '',
        isSelfPact: isSelfPact || 0
      });
      this.$store.commit('SET_UNITDATA', {
        unitId: data.unitId || 0,
        unitName: data.unitName || '',
        deptId: data.deptId || 0,
        deptName: data.deptName || '',
        checkType: data.checkType || -1,
        checkTypeName: data.checkTypeName || '',
        orgId: data.orgId || 0
      });
      setToken(token);
      setRefreshToken(data.token.refresh_token);
      setProjIds(data.projIds);
      setappServerId(data.appServerId);
      data.catalog && setCatalog(data.catalog);
    },
    formateDate(str, containHour = false) {
      if (!str) {
        return '';
      }
      let year = str.substr(0, 4);
      let month = str.substr(4, 2);
      let day = str.substr(6, 2);
      let hour = str.substr(8, 2);
      let mm = str.substr(10, 2);
      let ss = str.substr(12, 2);
      return containHour ? `${year}-${month}-${day} ${hour}:${mm}:${ss} ` : `${year}-${month}-${day} `;
    }
  },
  computed: {
    errorMsg: function () {
      return this.activeIndex === 1 ? this.errorMsg1 : this.errorMsg2;
    },
    ...mapState({
      // certsn: 'certsn',/* 已通过module拆分store */
      cert: state => state.userData.cert,
      certsn: state => state.userData.certsn,
      // loginType: state => state.userData.loginType,
      // deviceType: state => state.userData.deviceType
    })
  },
  watch: {
    cert: {
      handler: function (val, oldVal) {
        val && this.getUkeyList();
      },
      immediate: true
    }
  }
};
</script>

<style lang="scss" scoped>
$fontColor: rgba(0, 0, 0, 0.9);
$height: 4.1vh; //login_item 高度
$width: 18.8vw; //login_item 宽度
$minHeight: 18px;
$color: #d9e8fb;
$szcolor: #009943;
$fontBlue: #0080ff;

.login_wrap {
  width: 100%;
  height: 100vh;
  min-height: 500px;
  background-image: url('../../assets/image/login.png');
  background-size: cover;
  user-select: none;
  overflow: hidden;

  .systemName {
    margin-top: 17.6vh;
    margin-left: 12.8vw;

    p {
      color: #fff;

      &:first-of-type {
        font-size: 3.6vw;
        line-height: 3.6vw;
        margin-bottom: 3.3vh;
      }

      &:last-of-type {
        font-size: 2.7vw;
        line-height: 2.7vw;
        font-weight: bold;
      }
    }
  }

  .green,
  .city,
  .pic,
  .shadow_f,
  .shadow_l {
    display: none;
  }

  .login_f {
    position: fixed;
    width: 23.9vw;
    max-width: 100vw;
    // height: 48.5vh;
    min-height: 48.5vh;
    // min-height: 300px;
    // overflow: hidden;
    right: 12vw;
    top: 17.6vh;
    border-radius: 4px;
    display: flex;
    flex-direction: row;
    z-index: 99;

    //box-shadow: 0px 0px 10px rgba(255,255,255,.5);
    .img {
      flex: 1;
      height: 100%;
      background-color: transparent;

      img {
        width: 100%;
        height: 100%;
      }
    }

    .login {
      width: 23.9vw;
      height: 100%;
      min-width: 326px;
      // overflow-y: auto;
      // background-color: #fff;
      background-color: rgba(4, 12, 32, 0.45);
      border-radius: 4px;

      .title {
        display: block;
        font-size: 1.5vw;
        // line-height: 1.5vw;
        margin-top: 4.4vh;
        color: #fff;
        font-family: 'MicrosoftYaHei';
        width: 100%;
        text-align: center;
        text-decoration: none;
      }

      .form {
        margin-top: 4.8vh;
        width: 100%;
        height: 50%;
        position: relative;

        .tabs {
          width: 9.2vw;
          min-width: 120px;
          margin: 0 auto 2vh;
          height: 3.4vh;
          font-size: 14px;
          overflow: hidden;
          display: flex;
          justify-content: center;
          span {
            display: block;
            float: left;
            width: 50%;
            height: 100%;
            line-height: 3.4vh;
            font-size: 0.7vw;
            color: rgba(102, 102, 102, 1);

            // background-color: rgba(0,0,0,0.04);
            background-color: #d9e8fb;
            text-align: center;
            cursor: pointer;

            &:first-of-type {
              border-radius: 4px 0 0 4px;
              &:last-of-type {
                border-radius: 4px;
              }
            }

            &:last-of-type {
              border-radius: 0 4px 4px 0;
            }

            &.active {
              background-color: #0c7ff2;
              color: #fff;
            }
          }
        }

        .error {
          // position: absolute;
          margin: 0 auto;
          height: 15px;
          line-height: 15px;
          background-image: url(../../assets/image/warning.png);
          background-size: 12px 12px;
          background-repeat: no-repeat;
          background-position: 0 2px;
          max-width: $width;
          margin-bottom: 5px;
          line-height: 15px;
          width: fit-content;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          // left:0;
          // right:0;
          // margin: auto;
          // top:26px;
          text-align: center;
          padding-left: 17px;
          font-size: 12px;
          color: rgba(242, 73, 73, 1);
        }

        .tab_content {
          width: 100%;
          height: auto;
          overflow: hidden;
          padding: 0;
          .login_item {
            width: $width;
            height: $height;
            min-height: $minHeight;
            min-width: 256px;
            position: relative;
            margin: 1.54vh auto 0;
            display: flex;
            flex-direction: row;
            overflow: hidden;
          }
          .tab_1 {
            width: 100%;

            .login_item {
              .ipt >>> .el-input__inner {
                padding-left: 0px;
                margin-left: 50px;
              }
              .ipt >>> .el-input__prefix {
                top: 6px;
              }
              .el-input {
                background-color: $color;

                span {
                  color: #333333;
                  text-align: center;
                  font-size: 12px;
                }
              }
              &:first-of-type {
                margin-top: 0;
              }

              img {
                width: 6.3vw;
                height: calc(100% - 2px);
                min-width: 70px;
                position: absolute;
                right: 1px;
                top: 1px;
                z-index: 999;
              }
            }
          }

          .tab_2 {
            width: 100%;

            .ant-spin-nested-loading,
            .ant-spin-container {
              height: 100%;
              width: 100%;
            }

            .login_item {
              input {
                padding: 0 10px;
                color: $fontColor;
              }

              span {
                color: $fontColor;
              }

              .ipt >>> .el-input__inner {
                padding-left: 0px;
                margin-left: 50px;
              }
              .ipt >>> .el-input__prefix {
                top: 6px;
              }

              .ant-select-selection-placeholder {
                color: #bfbfbf;
              }

              .ant-select-single:not(.ant-select-customize-input)
                .ant-select-selector {
                height: 100%;

                input {
                  height: 100%;
                }
              }
              .txt {
                color: #fff;
                width: 70%;
                &.warning {
                  color: #f24949;
                }
              }

              .login_unlock {
                color: #40a9ff;
                cursor: pointer;
                width: 30%;
                text-align: right;
              }
            }

            .selectX {
              .el-select {
                width: 100%;
                .el-input__inner {
                  border-radius: 0px;
                }
              }
              > span {
                display: inline-block;
                width: 54px;
                padding-left: 6px;
                line-height: 32px;
                font-size: 12px;
                background-color: $color;
                color: #333;
              }
            }

            .el-input--prefix {
              background-color: $color;
              .el-input__inner {
                padding-left: 0;
                margin-left: 50px;
              }
              .el-input__prefix {
                top: 6px;
              }
              span {
                color: #333333;
                text-align: center;
                font-size: 12px;
              }
            }

            .el-input--small {
              padding: 0;
            }

            .ant-spin-blur {
              opacity: 0.1;
            }

            .ant-spin-text {
              text-shadow: none;
            }
          }

          .btn {
            width: $width;
            min-width: 256px;
            margin: 4.8vh auto;
            height: $height;
            min-height: $minHeight;
            padding: 0;
            display: block;

            button {
              width: 100%;
              height: $height;
              min-height: $minHeight;
              background-color: rgba(21, 123, 248, 1);
              border-radius: 4px;
              padding: 0;

              span {
                line-height: $height;
              }
            }
          }
        }
      }
    }
  }

  .bottomTxt {
    color: #fff;
    font-size: 14px;
    width: 400px;
    text-align: center;
    position: fixed;
    bottom: 30px;
    left: 50%;
    margin-left: -200px;
    z-index: 6;
    p {
      cursor: pointer;
      margin: 0;

      &:hover {
        text-decoration: underline;
      }
    }
  }
}
</style>